import Vue from 'vue'
import VueRouter from 'vue-router'
import routes from './modules'
import store from '../store'
// import errFun from 'utils/err'

import NProgress from 'nprogress' // Progress 进度条
import 'nprogress/nprogress.css' // Progress 进度条样式
import utils from 'utils'
import Layout from '@/views/layout'

Vue.use(VueRouter)
/** note: Submenu only appear when children.length>=1
/**
* hidden: true                   if `hidden:true` will not show in the sidebar(default is false)
* alwaysShow: true               if set true, will always show the root menu, whatever its child routes length
*                                if not set alwaysShow, only more than one route under the children
*                                it will becomes nested mode, otherwise not show the root menu
* redirect: noredirect           if `redirect:noredirect` will no redirect in the breadcrumb
* name:'router-name'             the name is used by <keep-alive> (must set!!!)
* meta : {
    roles: [roleId]                   will control the page roles (you can set multiple roles)['admin','editor']
    title: 'title'               the name show in submenu and breadcrumb (recommend set)
    icon: 'svg-name'             the icon show in the sidebar
    affix: true                  if set true, the tag will affix in the tags-view
    noCache: true                if true, the page will no be cached(default is false)
    breadcrumb: false            if false, the item will hidden in breadcrumb(default is true)
    activeMenu: '/example/list'  if set path, the sidebar will highlight the path you set
  }
**/

const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
  return originalPush.call(this, location).catch(err => err)
}

NProgress.configure({
  showSpinner: false
}) // NProgress Configuration

const demos = utils.isDebug ? require('../demos/routes').modules : {}

export const constantRoutes = [
  {
    path: '/404',
    component: () => import('@/views/404'),
    hidden: true
  },
  {
    path: '/401',
    component: () => import('@/views/401'),
    hidden: true
  },
  {
    path: '/login',
    name: 'login',
    component: () => import('@/views/login'),
    hidden: true
  },
  {
    path: '/',
    component: Layout,
    redirect: 'home',
    children: [
      {
        path: 'home',
        component: () => import('@/views/home'),
        name: 'home',
        meta: {
          title: 'home',
          icon: 'dashboard',
          noCache: true,
          affix: true
        }
      }
    ]
  },
  ...Object.values(demos)
]

// 通过解构数据屏蔽不需要引入到路由
// const { pay, ...routeOthers } = routes
export const asyncRoutes = [
  {
    path: '*',
    redirect: '/404',
    hidden: true
  },
  ...Object.values(routes).sort((a, b) => a.meta.sort - b.meta.sort)
]

// 不重定向白名单
const whiteList = new Set(['/login'])

const createRouter = () =>
  new VueRouter({
    routes: [...constantRoutes],
    mode: !utils.isDebug ? process.env.VUE_APP_ROUTEMODEL : 'hash',
    base: !utils.isDebug ? process.env.VUE_APP_BASEURLPATH : '',
    strict: utils.isDebug,
    scrollBehavior(to, from, savedPosition) {
      if (savedPosition) {
        return savedPosition
      } else {
        if (to.meta.keepAlive) {
          to.meta.savedPosition = document.body.scrollTop
        }
        return {
          x: 0,
          y: to.meta.savedPosition || 0
        }
      }
    }
  })

// 嵌入别的系统时，从url截取token // http://pillar-console.xxx.develop
const token = utils.getUrlParam('token')
if (token) {
  utils.setStore('token', token)
}

/**
 * 匹配权限
 * @param userPerms 用户拥有的权限集合，后台返回来，存在vuex，数据类型是数组
 * @param routerPerm 定义的src/router/index.js的路由表asyncRouterMap中
 * @returns {*}
 */
function hasPermission(userPerms, routerPerm) {
  // 特殊值，*代表所有资源权限
  if (userPerms.some(p => p.val == '*')) return true
  // 如果菜单路由上没有声明perm属性，默认显示该菜单，代表所有人可以访问
  if (!routerPerm) return true
  // 判断用户的资源权限集合中是否包含该菜单路由声明的资源权限
  return userPerms.some(p => p.val == routerPerm)
}

const router = createRouter()
router.beforeEach(async (to, from, next) => {
  NProgress.start()
  if (token || store.getters.token) {
    if (to.path === '/login') {
      next({
        path: '/'
      })
      NProgress.done()
    } else {
      if (store.getters.visitor) {
        // 1.2.1 若该标记为true,是因为getUserInfo返回结果发现用户信息中roles或perms为空数组，即未配置任何角色或权限，
        // 所以视为游客visitor给放行，放行后游客只能看到公共可以访问的菜单(即src/router/index.js中没有配置perm属性的路由)。
        next()
      } else if (!store.getters.roles || store.getters.roles.length === 0) {
        store
          .dispatch('user/getUserInfo', { token: token || store.getters.token })
          .then(res => {
            const perms = res.perms // note: roles must be a array! such as: [{name:'菜单1',val:'menu:1'}]
            store.dispatch('permission/generateRoutes', { perms }).then(routesList => {
              // 根据roles权限生成可访问的路由表
              router.addRoutes(routesList) // 动态添加可访问路由表
              next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
            })
          })
          .catch(err => {
            store.dispatch('user/frontLogout').then(() => {
              utils.confirmTip(err || '获取用户信息失败，请重试')
              next({ path: '/' })
            })
          })
      } else {
        // 1.2.3 如果vuex种有权限信息，匹配权限信息，匹配ok则放行
        if (hasPermission(store.getters.perms, to.meta.perm)) {
          next()
        } else {
          next({ path: '/401', replace: true, query: { noGoBack: true } })
        }
      }
    }
  } else {
    whiteList.has(to.path) ? next() : next(`/login?redirect=${to.path}`)
  }
})

router.afterEach(() => {
  NProgress.done() // 结束Progress
})

export function resetRouter() {
  const newRouter = createRouter()
  router.matcher = newRouter.matcher // reset router
}

export default router
